#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         Element.py
#
# Copyright:    Copyright (c) 2004, Faulkner Technologies
#
# Author:       Brian Oliver
#
# Description:  This file defines the abstract Element class, the 
#               base class of all Elements.
#
#               Elements are like a primitive form of Component, with the
#               expection they;
#
#               a). DON'T have any Ordering in a container 
#                   (either generic or component container).
#
#               b). DON'T have ShowIf functionality.
#
#               c). DON'T have any effect on Assessment Persistence.
#                   (they are not Assessible)
#
#               d). DON'T become indexed by Models
#
#               Possiblt Elements include; Headers, Footers, 
#               Toolbars, StyleSheets, Folders and Images
#
# See Also:     GenericObject, Component
#####################################################################

#####################################################################
## Knowledge Engine Library Imports
from Common import *
from GenericObject import GenericObject, GenericObjectInfo

#####################################################################
## Zope Library Imports
from Globals import DTMLFile
from ImageFile import ImageFile
from Acquisition import *

#####################################################################
## Python Library Imports
# (none)

#####################################################################
## ElementInfo Class Definition
class ElementInfo(GenericObjectInfo):
    """
        Defines the class info methods, defining information about
        the class without needing an instance of the class
    """
    
    #---------------------------------------------------------------#
    
    def getClassName(self):
        """
            Returns the name of the class for which 
            we are providing information.
        """
        return 'Element'

    #---------------------------------------------------------------#

    def getDisplayName(self):
        """
            Return a friendly name for the class instances
            (this is used for displaying in lists etc)
        """
    
        return "Element"
        
    #---------------------------------------------------------------#

    def getIdentityType(self):
        """
            Return the identity type.  
        """
        
        return "element"

    #---------------------------------------------------------------#

    def isContainer(self):
        """
            Returns if the instance is providing folderish/container
            services.
            
            Override an return true if the instance is to be
            a container for other instances.
            
            NOTE: all instances support "events" so there is no
            need to return true if you require "event" support.
        """

        #by default, elements aren't containers
        return false          

    #---------------------------------------------------------------#

    def isInstanceOf(self, className):
        """
            Returns if the class is an instance of the specified
            className, or implements the interface specified 
            by the className
        """

        return className == 'Element' or GenericObjectInfo.isInstanceOf(self, className)
        
    #---------------------------------------------------------------#

    def isPermittedInContainer(self, containerClassInfo, containerInstance = None, instance=None):
        """
            ABSTRACT: Returns if class instances (instance) is permitted in 
            the specified container (containerInstance)
            
            NOTE: This is from this class' instance perspective.
        """
        
        #DEFAULT RULE: Elements are permitted in Elements that are containers OR containers that permit elements
        #NOTE: containers may not permit them though!
        return (containerClassInfo.isInstanceOf("Element") and containerClassInfo.isContainer()) or containerClassInfo.isChildPermitted(self)

    #---------------------------------------------------------------#

    def isChildPermitted(self, childClassInfo, childInstance = None):
        """
            Returns if the specified child is permitted as a 
            child of the class' instances.
            
            NOTE: This is from this class' instance perspective.
            
            For component containers, this always overrides what the
            return value from childClassInfo.isPermittedInContainer(...)
        """
        
        #DEFAULT RULE: Elements may only have Children is they are containers
        return self.isContainer() and childClassInfo.isInstanceOf("Element")
    
    #---------------------------------------------------------------#

    def onConfigureProperties(self):
        """
            Automatically called by the Knowledge Engine once
            the class has been loaded.  Use this method to register 
            class specific properties using the PropertyReflection interface.
            
            If this class is sub-classed, a call must be made to
            the super-class to ensure super-class properties are
            correctly registered
            
            NOTE: This method is called before ClassInfo.onAfterStartup()            
        """

        #initialise the super-class properties for reflection
        GenericObjectInfo.onConfigureProperties(self)
     
     #---------------------------------------------------------------#
 
    def onConfigureEvents(self):
        """
            Automatically called by the Knowledge Engine once
            the class has been loaded.  Use this method to register 
            class specific events using the EventReflection interface.

            If this class is sub-classed, a call must be made to
            the super-class to ensure super-class properties are
            correctly registered

            NOTE: This method is called before ClassInfo.onAfterStartup()            
        """

        #initialise the super-class events for reflection
        GenericObjectInfo.onConfigureEvents(self)
    
    #---------------------------------------------------------------#

    def onConfigurePermissions(self):
        """
            Automatically called by the Knowledge Engine once
            the class has been loaded.  Use this method to register 
            class specific permission definitions.
            
            If this class is sub-classed, a call must be made to
            the super-class to ensure super-class properties are
            correctly registered
            
            NOTE: This method is called before ClassInfo.onAfterStartup()            
        """
        

        #initialise the super-class permissions for reflection
        GenericObjectInfo.onConfigurePermissions(self)
        
    #---------------------------------------------------------------#

#####################################################################
## Element Class Definition
class Element(GenericObject):
    """
        Base class for all KnowledgeEngine Elements
    """

    #---------------------------------------------------------------#

    #ABSTRACT TRANSIENT: a ClassInfo implementation instance to provide info about this class
    _CLASSINFO = ElementInfo()

    #---------------------------------------------------------------#

    # Custom zope manage_preview to permit previews of Elements.
    preview_html = DTMLFile('dtml/preview', globals())

    #---------------------------------------------------------------#

    def __init__(self, id, identity):
        "Constructor for the Element"        
        
        GenericObject.__init__(self, id, identity)

    #---------------------------------------------------------------#

    def onAfterInstanciation(self):
        """
            Handle Knowledge Engine specific actions after this object 
            has been loaded into memory.  
            
            This is useful for performing backwards compatibility
        """

        #preform default onAfterInstanciation processing
        GenericObject.onAfterInstanciation(self)

        #set the display position when in a Model
        self.updateDisplayPositionInModels()
        
        ###print "DEBUG: Element.onAfterInstanciation: Completed"
        
    #---------------------------------------------------------------#

    def onAfterPropertyChange(self, propertyName, oldValue, newValue):
        "Handle when an object property has changed (using the property editor)"

        #perform default processing
        GenericObject.onAfterPropertyChange(self, propertyName, oldValue, newValue)
       
    #---------------------------------------------------------------#

    def isPreviewPermitted(self):
        """
            Return if the Element is allowed to be previewed.
            
            By default all elements can't be previewed, some however
            should can be previewed. eg: HTMLHeaderFooters
        """
        
        return false
        
    #---------------------------------------------------------------#

    def getContent(self, contentZone, forGenericObject = None, assessment = None):
        """
            ABSTRACT: Return the Element generated 
            content for the specified contentZone (a string).   

            This method is called by the Model.index_html dtml file
            to customise the appearance of the output.
            
            By overriding this method, Elements have the opportunity
            to perform customization of the output from a Model
            during the assessment process.
            
            forGenericObject [optional] specifies the generic object
            instance for which the content is being requested.
            
            Standard Content Zones include: 
            "HTML_HEADER", 
            "TOOLBAR_TOP", "TOOLBAR_BOTTOM",
            "PAGE_HEADER", "PAGE_FOOTER"       
        """

        #by default, return nothing.
        return ""
        
    #---------------------------------------------------------------#

    def hasOwnOrder(self):
        """
            Returns if the Element defines it's own order and should not
            be destroyed by updateDisplayPositionInModels method
        """
        
        #DEFAULT: updateDisplayPositionInModels defines order
        return false
        
    #---------------------------------------------------------------#

    def isDisplayedBeforeComponents(self):
        """
            Returns if the Element is to be displayed before
            components in a model. Alternatively the Element is
            displayed after the components in a model.
            (If the element is in a model)
        """
        
        #DEFAULT: displayed after components
        return false
        
    #---------------------------------------------------------------#

    def updateDisplayPositionInModels(self):
        """
            Updates the display position in a Model based on
            the isDisplayedBeforeComponents() method
        """
        
        #has own order
        if not self.hasOwnOrder():
            #we set the order to correctly position the Element in Models (when in models)
            if self.isDisplayedBeforeComponents():
                self.order = -90000
            else:
                self.order = 90000
        
    #---------------------------------------------------------------#
    
#####################################################################
## Class Initialisation
# (none)
